home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-06-17 | 40.8 KB | 1,716 lines |
- Path: seismo!uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v10i008: Crypt Breaker's Workbench, Part08/11
- Message-ID: <390@uunet.UU.NET>
- Date: 19 Jun 87 03:17:17 GMT
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 1705
- Approved: rs@uunet.uu.net
-
- Submitted by: Robert W. Baldwin <BALDWIN@XX.LCS.MIT.EDU>
- Mod.sources: Volume 10, Issue 8
- Archive-name: cbw/Part08
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 8 (of 11)."
- # Contents: stats.c terminal.c
- # Wrapped by rs@uunet on Wed Jun 17 18:17:26 1987
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f stats.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"stats.c\"
- else
- echo shar: Extracting \"stats.c\" \(18796 characters\)
- sed "s/^X//" >stats.c <<'END_OF_stats.c'
- X/*
- X * Statistics routines.
- X *
- X * Robert W. Baldwin, January 1985.
- X * Scoring based on letter pairs added by Bob Baldwin May 1985.
- X */
- X
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "window.h"
- X#include "specs.h"
- X#include "cipher.h"
- X
- X
- X#define STANDALONE FALSE
- X
- X
- X
- X/* Globals */
- Xint stats1loaded = FALSE; /* True if letter stats loaded. */
- Xchar *letterstats; /* Filename to find single letter counts. */
- Xint stats2loaded = FALSE; /* True if letter pair stats loaded. */
- Xchar *bigramstats; /* Filename to find letter pair counts. */
- X
- X
- X/* This array contains the single letter frequencies.
- X * That is, prob[i] is the probability that a randomly selected
- X * plaintext character has ascii value i.
- X */
- Xfloat prob[MAXCHAR+1];
- Xfloat pmean, pvar; /* Mean and variance of above. */
- X
- X
- X/* This array contains the base ten logarithms of the single
- X * letter frequencies (probabilities) of ASCII characters.
- X * The frequencies are between 0 and 1, so the enteries in the
- X * table are between minus infinity and 0.
- X * The log of a vanishingly small frequency is represented as
- X * zero rather than some large negative number.
- X * The expected value of logprob[c] for a randomly selected
- X * character, c, is given by logmean. The variance of logprob[c]
- X * is given by logvar. The standard deviation is in logsd.
- X */
- Xfloat logprob[MAXCHAR+1];
- Xfloat logmean, logvar, logsd;
- X
- X
- X/* This array contains the bigram (letter pair) frequencies.
- X * That is, biprob[i][j] is the probability that a randomly selected
- X * pair of adjacent plaintext characters is Ai, Aj. Where Ai
- X * is the ith letter of the alphabet (0 = 'A' or 'a', and
- X * 26 = space or other non-alphabetic).
- X * Eventually this will be generalized to include an arbitrary
- X * character translation table to handle punctuation and to allow
- X * groups of characters such as (, <, {, and [ to be treated the same.
- X *
- X * The array slbiprob is the single letter frequencies taken from the
- X * same sources as biprob[][].
- X */
- Xfloat biprob[MXBIINDEX][MXBIINDEX];
- Xfloat slbiprob[MXBIINDEX];
- X
- X
- X/* The array is used to map from 7-bit ascii to indices in the biprob
- X * and related arrays. The variable nbichars is set to the next index
- X * to use in the biprob array.
- X */
- Xint char_bimap[MAXCHAR+1];
- Xint nbichars;
- X
- X
- X/* This array contains the base ten logarithms of the letter pair
- X * frequencies (biprob[][]).
- X * The frequencies are between 0 and 1, so the enteries in the
- X * table are between minus infinity and 0.
- X * The log of a vanishingly small frequency is represented as
- X * zero rather than some large negative number.
- X * The expected value of bilogprob[c] for a randomly selected
- X * character, c, is given by bilogmean. The variance of bilogprob[c]
- X * is given by bilogvar. The standard deviation is in bilogsd.
- X */
- Xfloat bilogprob[MXBIINDEX][MXBIINDEX];
- X
- X
- X/* This vector contains the base ten logarithms of the single letter
- X * frequencies which are derived from biprob[][].
- X * They are used to compute the log of the conditional probabilities
- X * of letter pairs, given a known value for either the first or
- X * second character.
- X * Specifically: log( prob(XY given X=Ai) ) equals
- X * log( prob(XY) / prob(Ai) ) which equals
- X * bilogprob[X][Y] - sllogprob[Ai].
- X */
- Xfloat sllogprob[MXBIINDEX];
- X
- X
- X/* The scoring function that uses letter pair frequencies is based
- X * on a statistic that has a computable mean and variance (and
- X * standard deviation). The are stored in the following variables.
- X */
- Xfloat score2_mean, score2_var, score2_sd, score2_scale;
- Xfloat score1_mean, score1_var, score1_sd, score1_scale;
- X
- X
- X#if STANDALONE
- X#define filename "/usr/baldwin/Ecrypt/mss-bigram.stats"
- Xmain()
- X{
- X FILE *inp;
- X
- X load_2stats_from(filename);
- X print_2stats(stdout);
- X}
- X#endif
- X
- X
- X
- X/* Score the given plaintext block. Returns a floating point number.
- X * For now a stud.
- X */
- Xfloat score(pblock)
- Xint pblock[];
- X{
- X int pchar;
- X int i;
- X float score;
- X
- X score = 0.0;
- X for (i = 0 ; i < BLOCKSIZE ; i++) {
- X pchar = pblock[i];
- X if (pchar == -1) continue;
- X if (pchar == ' ') {score += 0.1;}
- X else if (lletter(pchar)) {score += 0.1;}
- X else if (uletter(pchar)) {score += 0.05;}
- X else if (printable(pchar)) {score += 0.02;}
- X else if (pchar == '\t' || pchar == '\n' || pchar == '\f')
- X {score += 0.05;}
- X else if ('0' <= pchar && pchar <= '9')
- X {score += 0.05;}
- X else {score -= 0.4;}
- X }
- X return(score);
- X}
- X
- X
- X/* Score a vector of integers that represent characters.
- X * The vector is terminated by a value of NONE.
- X * The returned score is the number of standard deviations
- X * that the observed statistics differs from its expected value.
- X * Scores are positive with low scores being better.
- X * A negative score indicates an impossible plaintext value.
- X */
- Xfloat pvec_1score(pvec)
- Xint *pvec;
- X{
- X int i;
- X int c;
- X float tmp, sum, count, score;
- X
- X if (!stats1loaded) {
- X load_1stats_from(letterstats);
- X }
- X
- X count = 0.0;
- X sum = 0.0;
- X while (*pvec != NONE) {
- X count += 1.0;
- X c = *pvec++;
- X if (c != c & CHARMASK) return(-1.0);
- X tmp = logprob[c & CHARMASK];
- X if (tmp == 0.0) return(-1.0);
- X sum += tmp;
- X }
- X
- X if (count == 0.0) return(-1.0);
- X tmp = (sum / count) - logmean;
- X tmp = tmp > 0 ? tmp : 0.0 - tmp;
- X score = tmp / (logsd / sqrt(count));
- X/* printf(" dividing by logsd yields %g", score);
- X tmp = tmp * tmp;
- X tmp = (tmp * count) / logvar;
- X tmp = exp(-0.5 * tmp);
- X printf("\nThe exponential yields %g", tmp);
- X printf("\n");
- X score = sqrt(count) * exp((0 - tmp)/2.0);
- X*/
- X return(score);
- X}
- X
- X
- X/* Score a vector of integers that represent characters.
- X * The vector is terminated by a value of NONE.
- X * Scoring is based on ratio of observed and expected variance.
- X */
- Xfloat var_1score(pvec)
- Xint *pvec;
- X{
- X int i;
- X int c;
- X float tmp, sum, count, score;
- X
- X if (!stats1loaded) {
- X load_1stats_from(letterstats);
- X }
- X
- X count = 0.0;
- X sum = 0.0;
- X while (*pvec != NONE) {
- X count += 1.0;
- X c = *pvec++;
- X if (c != c & CHARMASK) return(0.0);
- X tmp = logprob[c & CHARMASK];
- X if (tmp == 0.0) return(0.0);
- X tmp = tmp - logmean;
- X tmp = tmp * tmp;
- X sum += tmp;
- X }
- X
- X if (count == 0.0) return(0.0);
- X score = sum / (count * logvar);
- X return(score);
- X}
- X
- X
- X/* Score a vector of integers that represent characters.
- X * The vector is terminated by a value of NONE.
- X * Score is the probability that the given characters
- X * were drawn from english.
- X * NOTE: doesn't correctly handle repeated letters.
- X */
- Xfloat prob_1score(pvec)
- Xint *pvec;
- X{
- X int i;
- X int c;
- X float tmp, product, count, score;
- X
- X if (!stats1loaded) {
- X load_1stats_from(letterstats);
- X }
- X
- X count = 0.0;
- X product = 1.0;
- X while (*pvec != NONE) {
- X count += 1.0;
- X c = *pvec++;
- X if (c != c & CHARMASK) return(0.0);
- X product *= prob[c] * count;
- X }
- X
- X if (count == 0.0) return(0.0);
- X score = product;
- X return(score);
- X}
- X
- X
- X/* Score a guess based on letter pair frequencies.
- X * The returned score is the number of standard deviations
- X * that the observed statistics differs from its expected value.
- X * Scores are positive with low scores being better.
- X * A negative score indicates an impossible plaintext value.
- X */
- Xfloat gsi_2score(gsi)
- Xreg gsinfo *gsi;
- X{
- X float score;
- X float total;
- X float tmp;
- X int nchars;
- X int i;
- Xreg int pos;
- Xreg int c;
- Xreg int center_letter;
- X int left_letter, right_letter;
- X float pair_score;
- X
- X if (!stats2loaded) {
- X load_2stats_from(bigramstats);
- X }
- X
- X nchars = 0;
- X total = 0.0;
- X for (i = 0 ; (pos = gsi->cpos[i]) != NONE ; i++) {
- X nchars++;
- X c = (gsi->cguessed)[pos];
- X center_letter = char_bimap[c & CHARMASK];
- X if (sllogprob[center_letter] == 0.0)
- X return(-1.0);
- X
- X if (pos == 0) {
- X total += sllogprob[center_letter];
- X }
- X else {
- X c = (gsi->cknown)[pos - 1];
- X if (c == NONE) {
- X c = (gsi->cguessed)[pos - 1];
- X }
- X if (c == NONE) {
- X total += sllogprob[center_letter];
- X }
- X else {
- X left_letter = char_bimap[c & CHARMASK];
- X pair_score = bilogprob[left_letter][center_letter];
- X if (pair_score == 0.0)
- X return(-1.0);
- X total += pair_score - sllogprob[center_letter];
- X }
- X }
- X
- X if (pos == (BLOCKSIZE - 1)) {
- X total += sllogprob[center_letter];
- X }
- X else {
- X c = (gsi->cknown)[pos + 1];
- X if (c == NONE) {
- X c = (gsi->cguessed)[pos + 1];
- X }
- X if (c == NONE) {
- X total += sllogprob[center_letter];
- X }
- X else {
- X right_letter = char_bimap[c & CHARMASK];
- X pair_score = bilogprob[center_letter][right_letter];
- X if (pair_score == 0.0)
- X return(-1.0);
- X total += pair_score - sllogprob[center_letter];
- X }
- X }
- X }
- X
- X if (nchars == 0)
- X return(-1.0);
- X tmp = (total / nchars) - score2_mean;
- X tmp = tmp > 0.0 ? tmp : 0.0 - tmp;
- X score = tmp / (score2_sd / isqrt[nchars]);
- X return(score);
- X}
- X
- X
- X/* Score a guess based on single letter frequencies.
- X * The returned score is the number of standard deviations
- X * that the observed statistics differs from its expected value.
- X * Scores are positive with low scores being better.
- X * A negative score indicates an impossible plaintext value.
- X */
- Xfloat gsi_1score(gsi)
- Xreg gsinfo *gsi;
- X{
- Xreg int pos;
- X int i;
- X int c;
- X int nchars;
- X float sum, score;
- Xreg float tmp;
- X
- X if (!stats1loaded) {
- X load_1stats_from(letterstats);
- X }
- X
- X nchars = 0;
- X sum = 0.0;
- X for (i = 0 ; (pos = gsi->cpos[i]) != NONE ; i++) {
- X nchars++;
- X c = (gsi->cguessed)[pos];
- X tmp = logprob[c & CHARMASK];
- X if (tmp == 0.0)
- X return(-1.0);
- X sum += tmp;
- X }
- X
- X if (nchars == 0)
- X return(-1.0);
- X tmp = (sum / nchars) - logmean;
- X tmp = tmp > 0 ? tmp : 0.0 - tmp;
- X score = tmp / (logsd / isqrt[nchars]);
- X
- X return(score);
- X}
- X
- X
- X/* Compute expected value of a scoring function given
- X * a vector of probabilities for values and a vector of
- X * scores for each value.
- X */
- Xfloat vec_mean(probvec, scorevec, maxindex)
- Xfloat *probvec;
- Xfloat *scorevec;
- Xint maxindex;
- X{
- X int i;
- X float mean;
- X
- X mean = 0.0;
- X for (i = 0 ; i <= maxindex ; i++) {
- X mean += (*probvec++) * (*scorevec++);
- X }
- X return(mean);
- X}
- X
- X
- X/* Compute variance of a scoring function given
- X * a vector of probabilities for values and a vector of
- X * scores for each value.
- X */
- Xfloat vec_variance(probvec, scorevec, maxindex)
- Xfloat *probvec;
- Xfloat *scorevec;
- Xint maxindex;
- X{
- X int i;
- X float var, mean;
- X float delta;
- X
- X mean = vec_mean(probvec, scorevec, maxindex);
- X var = 0.0;
- X for (i = 0 ; i <= maxindex ; i++) {
- X delta = (*scorevec++) - mean;
- X var += (*probvec++) * (delta * delta);
- X }
- X return(var);
- X}
- X
- X
- X/* Read from given stream to set up logprob table and constants
- X * logmean and logvar.
- X *
- X * The table format is:
- X * <Total count>
- X * <Blankline>
- X * <Count><space><One or more slashified characters to share that count>
- X * ...
- X * <Count><space><One or more slashified characters to share that count>
- X * <Blankline>
- X * <EOF>
- X */
- Xload_1stats(inp)
- XFILE *inp;
- X{
- X int i,n;
- X int tmp;
- X int c;
- X float v, lv, fv;
- X float etotal, ctotal;
- X
- X stats1loaded = TRUE;
- X
- X for (i = 0 ; i <= MAXCHAR ; i++) logprob[i] = 0.0;
- X
- X if (fscanf(inp, "%d", &tmp) != 1) {
- X printf("Error while getting total");
- X return;
- X }
- X etotal = tmp;
- X ctotal = 0.0;
- X
- X if (fscanf(inp, "\n") != 0) {
- X printf("Error while skipping blank line");
- X return;
- X }
- X
- X while (TRUE) {
- X if ((n = fscanf(inp, "%d", &tmp)) != 1) {
- X if (n == 0) break;
- X if (n == EOF) break;
- X printf("Error while getting character count");
- X return;
- X }
- X v = tmp;
- X ctotal += v;
- X fv = v/etotal;
- X if (fv != 0.0) {lv = log10(fv);}
- X else {lv = 0.0;}
- X
- X c = read_char(inp); /* Skip the space. */
- X while (TRUE) {
- X c = read_char(inp);
- X if (c == EOL) break;
- X prob[c&CHARMASK] = fv;
- X logprob[c&CHARMASK] = lv;
- X }
- X }
- X
- X if (etotal != ctotal) {
- X printf("Expected total is %f. Actual total is %f.\n",etotal,ctotal);
- X }
- X
- X logmean = vec_mean(prob, logprob, MAXCHAR);
- X logvar = vec_variance(prob, logprob, MAXCHAR);
- X logsd = sqrt(logvar);
- X score1_mean = logmean;
- X score1_var = logvar;
- X score1_sd = logsd;
- X score1_scale = sqrt(2 * PI * score1_var);
- X pmean = vec_mean(prob, prob, MAXCHAR);
- X pvar = vec_variance(prob, prob, MAXCHAR);
- X}
- X
- X
- X/* Load the letter pair statistics from the given file name.
- X */
- Xload_2stats_from(statfname)
- Xchar *statfname; /* Full path name of file with statistics. */
- X{
- X FILE *inp;
- X
- X if ((inp = fopen(statfname, "r")) == NULL) {
- X printf("\nCan't open %s to read letter statistics\n", statfname);
- X exit(0);
- X }
- X load_2stats(inp);
- X fclose(inp);
- X}
- X
- X
- X/* Read from given stream to set up bilogprob table and constants
- X * bilogmean, bilogsd, and bilogvar.
- X *
- X * The format of the statistics file is: [This should be more general.]
- X * <Total count>
- X * <Blankline>
- X * <single letter counts>
- X * <line with the chars '***'>
- X * <double letter counts>
- X * <line with the chars '***'>
- X * <mean of matrix>
- X * <variance of matrix>
- X * <standard deviation of matrix>
- X * <Blankline>
- X * <EOF>
- X *
- X * Where single letter counts also define the mapping from ascii chars to
- X * distinguished letters (i.e., all open brackets are treated the same).
- X * The single letter format is:
- X * <Count><space><One or more slashified characters to share that count>
- X * ...
- X * <Count><space><One or more slashified characters to share that count>
- X * NOTE: the first entry should be for a low probability letter because the
- X * default mapping for unknown chars is zero. See code for details.
- X *
- X * The double letter format is:
- X * <Count><space><Representative of first letter group><Rep of second letter>
- X * ...
- X * <Count><space><Representative of first letter group><Rep of second letter>
- X *
- X * For example if 'T' and 't' are treated the same, a double letter entry
- X * might look like: "1247 TT" and count for Tt, tT, tt, and TT.
- X */
- Xload_2stats(inp)
- XFILE *inp;
- X{
- Xregister int i,j;
- X int n;
- X int tmp;
- X int c;
- X int left_index, right_index;
- X float v, lv, fv;
- X float etotal, ctotal;
- X char linebuf[300];
- X
- X stats2loaded = TRUE;
- X nbichars = 0;
- X
- X for (i = 0 ; i < MXBIINDEX ; i++) {
- X sllogprob[i] = 0.0;
- X slbiprob[i] = 0.0;
- X for (j = 0 ; j < MXBIINDEX ; j++) {
- X bilogprob[i][j] = 0.0;
- X biprob[i][j] = 0.0;
- X }
- X }
- X
- X for (i = 0 ; i < MAXCHAR+1 ; i++)
- X char_bimap[i] = 0; /* Default index if char unknown. */
- X
- X if (fscanf(inp, "%d", &tmp) != 1) {
- X printf("Error while getting total");
- X exit(0);
- X }
- X etotal = tmp;
- X
- X if (fscanf(inp, "\n") != 0) {
- X printf("Error while skipping blank line before single letters");
- X exit(0);
- X }
- X
- X ctotal = 0.0;
- X while (TRUE) {
- X if ((n = fscanf(inp, "%d", &tmp)) != 1) {
- X if (n == 0) break;
- X if (n == EOF) break;
- X printf("Error while getting character count (singles)");
- X exit(0);
- X }
- X v = tmp;
- X ctotal += v;
- X fv = v/etotal;
- X if (fv == 0.0)
- X lv = 0.0;
- X else
- X lv = log10(fv);
- X
- X c = read_char(inp); /* Skip the space. */
- X while (TRUE) {
- X c = read_char(inp);
- X if (c == EOL) break;
- X char_bimap[c & CHARMASK] = nbichars;
- X slbiprob[nbichars] = fv;
- X sllogprob[nbichars] = lv;
- X }
- X nbichars++;
- X }
- X
- X if (etotal != ctotal) {
- X printf("Expected total is %f. Actual total is %f for singles.\n",
- X etotal, ctotal);
- X exit(0);
- X }
- X
- X
- X if (fscanf(inp, "***\n") != 0) {
- X printf("Error on delimiter before letter pairs");
- X exit(0);
- X }
- X
- X ctotal = 0.0;
- X while (TRUE) {
- X if ((n = fscanf(inp, "%d", &tmp)) != 1) {
- X if (n == 0) break;
- X if (n == EOF) break;
- X printf("Error while getting character count (pairs)");
- X exit(0);
- X }
- X v = tmp;
- X ctotal += v;
- X fv = v/etotal;
- X if (fv == 0.0)
- X lv = 0.0;
- X else
- X lv = log10(fv);
- X
- X c = read_char(inp); /* Skip the space. */
- X c = read_char(inp); /* First letter. */
- X if (c == EOL) {
- X printf("Line ends before letter pair");
- X exit(0);
- X }
- X left_index = char_bimap[c & CHARMASK];
- X c = read_char(inp); /* Second letter. */
- X if (c == EOL) {
- X printf("Line ends in middle of letter pair");
- X exit(0);
- X }
- X right_index = char_bimap[c & CHARMASK];
- X
- X biprob[left_index][right_index] = fv;
- X bilogprob[left_index][right_index] = lv;
- X }
- X
- X if (etotal != ctotal) {
- X printf("Expected total is %f. Actual total is %f for pairs.\n",
- X etotal, ctotal);
- X exit(0);
- X }
- X
- X if (fscanf(inp, "***\n") == 0) {
- X if (fscanf(inp, "%f", &score2_mean) != 1) {
- X printf("Error reading mean.");
- X exit(0);
- X }
- X if (fscanf(inp, "%f", &score2_var) != 1) {
- X printf("Error reading variance.");
- X exit(0);
- X }
- X if (fscanf(inp, "%f", &score2_sd) != 1) {
- X printf("Error reading standard deviations.");
- X exit(0);
- X }
- X score2_scale = sqrt(2 * PI * score2_var);
- X approx_init();
- X return;
- X }
- X
- X stats2();
- X printf("Mean: %f, Var: %f, SD: %f\n", score2_mean, score2_var, score2_sd);
- X}
- X
- X
- X/* Compute scoring statistics for the letter pair frequencies.
- X * Uses the globals: biprob[][], sllogbiprob[], and bilogprob[][].
- X * Sets gobals: score2_mean, score2_var, score2_sd.
- X */
- Xstats2()
- X{
- Xregister int i,j,k;
- X float mean, var;
- X float weight, score;
- X
- X mean = 0.0;
- X var = 0.0;
- X for (i = 0 ; i < nbichars ; i++)
- X for (j = 0 ; j < nbichars ; j++) {
- X if (slbiprob[j] == 0.0)
- X continue;
- X for (k = 0 ; k < nbichars ; k++) {
- X weight = biprob[i][j] * biprob[j][k] / slbiprob[j];
- X score = bilogprob[i][j] + bilogprob[j][k] - 2 * sllogprob[j];
- X mean += weight * score;
- X var += weight * score * score;
- X }
- X }
- X var -= mean * mean;
- X
- X score2_mean = mean;
- X score2_var = var;
- X score2_sd = sqrt(score2_var);
- X score2_scale = sqrt(2 * PI * score2_var);
- X
- X approx_init();
- X}
- X
- X
- X/* Print the bigram statistics.
- X */
- Xprint_2stats(out)
- XFILE *out;
- X{
- X float sllog_mean;
- X float sllog_var;
- X float lev_mean, lev_var;
- X float rev_mean, rev_var;
- X
- X fprintf(out, "\t\tBigram Statistics\n");
- X fprintf(out, "Score2_mean is %f", score2_mean);
- X fprintf(out, ", score2_var is %f", score2_var);
- X fprintf(out, ", score2_sd is %f", score2_sd);
- X fprintf(out, "\nnbichars is %d", nbichars);
- X fprintf(out, "\n");
- X
- X sllog_mean = vec_mean(slbiprob, sllogprob, nbichars);
- X sllog_var = vec_variance(slbiprob, sllogprob, nbichars);
- X fprintf(out, "sllog_mean is %f", sllog_mean);
- X fprintf(out, ", sllog_var is %f", sllog_var);
- X fprintf(out, "\n");
- X}
- X
- X
- X
- X/* Print the first order log statistics on a stream.
- X */
- Xprint_1stats(out)
- XFILE *out;
- X{
- X
- X fprintf(out, "Single letter frequencies\n");
- X fprintf(out, "\nExpected value of prob is %f. Variance is %f.\n",
- X pmean, pvar);
- X print_stat_tab(out, prob, MAXCHAR);
- X
- X fprintf(out, "\nExpected value of logprob is %f. Variance is %f.\n",
- X logmean, logvar);
- X fprintf(out, "Log of single letter frequencies\n");
- X print_stat_tab(out, logprob, MAXCHAR);
- X}
- X
- X
- X/* Dumpa statistics table on to a stream.
- X */
- Xprint_stat_tab(out, table, maxindex)
- XFILE *out;
- Xfloat table[];
- Xint maxindex;
- X{
- X int i;
- X
- X for (i = 0 ; i <= maxindex ; i++) {
- X if (i % 8 == 0) fprintf(out, "\n");
- X fprintf(out, "%7.4f ", table[i]);
- X }
- X fprintf(out, "\n");
- X}
- X
- X
- X/* Load the first order statistics from the given file name.
- X */
- Xload_1stats_from(statfname)
- Xchar *statfname;
- X{
- X FILE *inp;
- X
- X if ((inp = fopen(statfname, "r")) == NULL) {
- X printf("\nCan't open %s to read letter statistics\n", statfname);
- X exit(0);
- X }
- X load_1stats(inp);
- X fclose(inp);
- X}
- X
- END_OF_stats.c
- if test 18796 -ne `wc -c <stats.c`; then
- echo shar: \"stats.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f terminal.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"terminal.c\"
- else
- echo shar: Extracting \"terminal.c\" \(19285 characters\)
- sed "s/^X//" >terminal.c <<'END_OF_terminal.c'
- X/* Terminal dependent routines (well, most of them ...)
- X *
- X * Author: Bob Baldwin, October 1986.
- X */
- X
- X/*
- X * Routines in terminal abstraction:
- X *
- X * set_term()
- X * Initialize terminal, clear the screen.
- X *
- X * unset_term()
- X * Return terminal to state before set_term().
- X *
- X * char2sym(char)
- X * Return the symbol used to display the given char in the
- X * decryption window.
- X *
- X * putsym(symbol)
- X * Displays the given symbol on the terminal. Handles
- X * entering and exiting graphics mode.
- X *
- X * getcmd()
- X * Reads stdin for a keystroke and returns
- X * a command integer.
- X *
- X * beep()
- X * Cause the terminal to beep or flash.
- X */
- X
- X/* The trick to device independence is to clearly separate
- X * internal and external representations. On the inbound
- X * side, we separate KEYSTOKES which generate a sequence
- X * of ascii characters (one per keystroke in the simple case),
- X * from COMMAND-KEYS such as move-cursor-up. On the outbound
- X * side we separate SYMBOLS from the sequence of ascii characters,
- X * called GRAPHICS, used to display the symbol. Each symbol
- X * has a single use by the code, though two symbols might
- X * appear the same on the user's terminal.
- X */
- X
- X/* Symbols are represented by integers. If the integer is
- X * greater than 256, then it denotes one of the symbols defined
- X * in terminal.h.
- X *
- X * Commands are represented by two byte integers. The high byte
- X * describes the command (see terminal.h), the low byte is the
- X * argument to the command. For example, the insert char command
- X * sets the low byte to the character to be inserted.
- X */
- X
- X/* INTERNALS: symbols and graphics
- X *
- X * The terminal is assumed to be in one of three modes: normal, graphics,
- X * or standout (inverse video). This abstraction takes care of all the
- X * switching between modes and tries to avoid sending redundant escape
- X * sequences to the terminal.
- X *
- X * Part of the terminal initialization is to build a table that describes
- X * how to display each symbol. Ascii characters (including control chars)
- X * pass through unchanged, but symbols are looked up in graphtab.
- X * Each entry in the graphics table specifies a terminal mode and a
- X * string to print that will display that symbol in the given mode.
- X * If necessary a mode switch sequence will be sent before printing the
- X * string.
- X *
- X * The graphics corresponding to symbols can be set by the shell variable
- X * 'GRAHPICS' using a format similar to the termcap format. The two
- X * character names of the symbols are defined in the table symnames[],
- X * which can be indexed by the symbol codes (see terminal.h).
- X * The mapping from symbols to graphics is first set to a default value,
- X * and then updated by the values found in the shell variable (if any).
- X *
- X * The GRAPHICS string consists of a number of entries separated by colon
- X * characters. Each entry have the form xx=\Mccc, where xx is the name
- X * of a symbol (see symnames[] below), \M indicates the mode for displaying
- X * this symbol (it must be one of \N (for normal), \G (for graphics), or \S
- X * (for standout or inverse video)), and ccc is a sequence of characters
- X * to send. To include a colon character in the ccc portion, preceed it
- X * by a backslash (i.e., '\'). If the \M is ommitted, it defaults to normal.
- X */
- X
- X/* INTERNALS: keystrokes and commands
- X *
- X * The table keycmdtab is used to convert a sequence of ascii characters
- X * into a command integer. The table specifies the escape sequences that
- X * might be generated by the different command keys. The getcmd routine
- X * will read characters from stdin until it has uniquely identified a
- X * command, or decided that there is no match. If no match is found,
- X * the terminal is beeped and matching is restarted with the next character.
- X * By default keystrokes turn into self-insert commands.
- X *
- X * In general the last character of the sequence is returned as the arg.
- X * This helps windows assign different meanings to keystokes. For example
- X * The return key can be either an insert-return command or an execute-
- X * command-line command.
- X */
- X
- X
- X#include <curses.h>
- X#include <sgtty.h>
- X#include <strings.h>
- X#include "window.h"
- X#include "terminal.h"
- X#include "specs.h"
- X
- X
- X/* Routines from termcap library.
- X */
- Xextern char *getenv(), *tgetstr(), *tgoto();
- X
- X
- X/* Screen control strings from termcap entry.
- X */
- Xchar *term_is; /* Terminal initializaion string. */
- Xchar *erase_eol; /* Erase to end of line. */
- Xchar *erase_eos; /* Erase to end of screen. */
- Xchar *erase_scr; /* Erase whole screen. */
- Xchar *cm; /* Cursor motion. */
- Xchar *start_kp; /* Start graphics mode. */
- Xchar *end_kp; /* End graphics mode. */
- Xchar *start_alt; /* Start graphics mode. */
- Xchar *end_alt; /* End graphics mode. */
- Xchar *start_so; /* Start standout mode. */
- Xchar *end_so; /* End standout mode. */
- X
- X/* Keymap strings from termcap file.
- X */
- Xchar *term_f1; /* The f1 key. */
- Xchar *term_f2; /* The f2 key. */
- Xchar *term_f3; /* The f3 key. */
- Xchar *term_f4; /* The f4 key. */
- Xchar *term_up; /* Up arrow. */
- Xchar *term_down; /* Down arrow. */
- Xchar *term_left; /* Left arrow. */
- Xchar *term_right; /* Right arrow. */
- X
- X
- X/* Symbol names for the shell variable 'GRAPHICS'
- X * The values must be and'ed with SYMBOLM to make
- X * suitable indices for graphtab[].
- X */
- Xlabelv symnames[NSYMC + 1] = {
- X {"tb", STAB}, /* Tab */
- X {"na", SNOTASCII}, /* Not ascii */
- X {"lf", SLINEFEED}, /* Linefeed */
- X {"cr", SCARETURN}, /* Carriage return */
- X {"ff", SFORMFEED}, /* Formfeed */
- X {"cc", SCONTCODE}, /* Other control characters */
- X {"uk", SUNKNOWN}, /* Plaintext unknown */
- X {"ul", SUNDERLINE}, /* Pseudo underline char */
- X {"hb", SHORZBAR}, /* Horizontal bar */
- X {"vb", SVERTBAR}, /* Vertical bar */
- X {"ll", SLLCORNER}, /* Lower left corner */
- X {NULL, 0}, /* End flag. */
- X};
- X
- X/* Table of graphics characters initialized for ordinary CRT.
- X */
- Xsymgraph graphtab[NSYMC];
- X
- X
- X/* Symbol names for the shell variable KEYMAPVAR
- X * A command's index in this table should be one less
- X * than the command code.
- X */
- Xlabelv cmdnames[] = {
- X {"up", CGO_UP},
- X {"do", CGO_DOWN},
- X {"le", CGO_LEFT},
- X {"ri", CGO_RIGHT},
- X {"re", CREFRESH},
- X {"un", CUNDO},
- X {"cl", CCLRLINE},
- X {"ws", CWRDSRCH},
- X {"df", CDELF},
- X {"db", CDELB},
- X {"pr", CPREVBLOCK},
- X {"ne", CNEXTBLOCK},
- X {"ac", CACCEPT},
- X {"ex", CEXECUTE},
- X {"--", CINSERT}, /* Should not be in keymap var. */
- X {"ta", CTRYALL},
- X {"jc", CJUMPCMD},
- X {NULL, 0},
- X};
- X
- X/* Table of keystroke commands.
- X * Self-insert commands are the default.
- X * There can be several keystrokes that generate the same command.
- X * To insert control chars, they must be quoted, see QUOTEC.
- X * The table is terminated by an entry with c_seq == NULL.
- X */
- X#define QUOTEC (CNTRL & 'Q')
- Xkeycmd keycmdtab[100];
- Xkeycmd *keycmdp; /* Pointer to next free entry. */
- X
- X
- X
- X/* Saved process control characters.
- X */
- Xstruct tchars saved_tchars;
- X
- X
- X/* Buffer for termcap entry. */
- X#define TBUFSIZ 1024
- Xchar buf[TBUFSIZ];
- Xchar free_buf[1000], *fr; /* Must be global, see tgetstr() */
- X
- X
- X/* Current terminal mode. */
- Xint termmode = -1;
- X
- X
- X/* Set up the terminal. This package now makes calls to both curses
- X * and termcap subroutine packages, although the old code is used
- X * for screen refresh.
- X */
- Xset_term()
- X{
- X printf("\n\nInitializing terminal ...");
- X fflush(stdout);
- X
- X get_termstrs();
- X get_genv();
- X get_kenv();
- X savetty();
- X crmode();
- X noecho();
- X noflow();
- X Puts(term_is);
- X Puts(start_kp);
- X enter_mode(SMNORMAL);
- X
- X printf(" done.\n");
- X
- X clrscreen();
- X}
- X
- X
- X/* Get keystroke characters, build keymap.
- X * The earlier entries have priority, so fill them in from
- X * the shell var, then add defaults from a string then termcap.
- X */
- Xget_kenv()
- X{
- X char *kenv;
- X char tcapstr[1000];
- X
- X keycmdp = keycmdtab;
- X kenv = getenv(KEYMAPVAR);
- X if (kenv != NULL)
- X read_keymap(kenv);
- X kenv_termcap(tcapstr);
- X read_keymap(tcapstr);
- X read_keymap(DKEYMAP);
- X}
- X
- X
- X/* Build a keymap string in the given buffer from the info
- X * in the termcap file.
- X * The string format is like: "up=\Eu:do=\033d".
- X */
- Xkenv_termcap(str)
- Xchar *str;
- X{
- X *str = NULL;
- X
- X if (term_up != NULL) {
- X strcat(str, cmdnames[CGO_UP - 1].label);
- X strcat(str, "=");
- X strcat(str, term_up);
- X strcat(str, ":");
- X }
- X if (term_down != NULL) {
- X strcat(str, cmdnames[CGO_DOWN - 1].label);
- X strcat(str, "=");
- X strcat(str, term_down);
- X strcat(str, ":");
- X }
- X if (term_left != NULL) {
- X strcat(str, cmdnames[CGO_LEFT - 1].label);
- X strcat(str, "=");
- X strcat(str, term_left);
- X strcat(str, ":");
- X }
- X if (term_right != NULL) {
- X strcat(str, cmdnames[CGO_RIGHT - 1].label);
- X strcat(str, "=");
- X strcat(str, term_right);
- X strcat(str, ":");
- X }
- X if (term_f1 != NULL) {
- X strcat(str, cmdnames[CPREVBLOCK - 1].label);
- X strcat(str, "=");
- X strcat(str, term_f1);
- X strcat(str, ":");
- X }
- X if (term_f2 != NULL) {
- X strcat(str, cmdnames[CNEXTBLOCK - 1].label);
- X strcat(str, "=");
- X strcat(str, term_f2);
- X strcat(str, ":");
- X }
- X if (term_f3 != NULL) {
- X strcat(str, cmdnames[CACCEPT - 1].label);
- X strcat(str, "=");
- X strcat(str, term_f3);
- X strcat(str, ":");
- X }
- X if (term_f4 != NULL) {
- X strcat(str, cmdnames[CJUMPCMD - 1].label);
- X strcat(str, "=");
- X strcat(str, term_f4);
- X strcat(str, ":");
- X }
- X}
- X
- X
- X
- X/* Add key bindings from the given string to the keycmdtab.
- X */
- Xread_keymap(var)
- Xchar *var;
- X{
- X int cmd_code;
- X
- X while (*var != NULL) {
- X if (! read_varlabel(&var, cmdnames, &cmd_code)) {
- X if (*var == NULL)
- X break;
- X disperr("Can't parse label in read_keymap.");
- X exit(1);
- X }
- X
- X keycmdp->c_code = cmd_code;
- X if (! read_varval(&var, &(keycmdp->c_seq))) {
- X disperr("keymap value has bad format.");
- X exit(1);
- X }
- X keycmdp++;
- X }
- X}
- X
- X
- X/* Get graphics characters.
- X * Set to defaults, then read changes from shell var (if any).
- X */
- Xget_genv()
- X{
- X char *genv;
- X
- X read_graphics(DGRAPHICS);
- X genv = getenv(GRAPHICSVAR);
- X if (genv == NULL)
- X return;
- X read_graphics(genv);
- X}
- X
- X
- X/* Read graphics map from the given string.
- X */
- Xread_graphics(var)
- Xchar *var;
- X{
- X int sym_idx;
- X
- X while (*var != NULL) {
- X if (! read_varlabel(&var, symnames, &sym_idx)) {
- X if (*var == NULL)
- X break;
- X disperr("Can't parse label in GRAPHICSMAP.");
- X exit(1);
- X }
- X
- X if ((var[0] != '\\') || (index(GVARMODES, var[1]) == 0)) {
- X disperr("GRAPHICSMAP value has bad mode.");
- X exit(1);
- X }
- X sym_idx &= SYMBOLM;
- X graphtab[sym_idx].s_mode = var[1] & CHARM;
- X var++, var++;
- X
- X if (! read_varval(&var, &(graphtab[sym_idx].s_seq))) {
- X disperr("GRAPHICSMAP val has bad format.");
- X exit(1);
- X }
- X }
- X}
- X
- X
- X/* Advance to the next label in strp, look the label up in the
- X * labeltab, and set *valp to the value in the labeltab.
- X * Return with *strp pointing after '=' that follows the label.
- X * Return TRUE is parses ok, else return FALSE.
- X * If string empty, return false and set *strp to point to a NULL.
- X */
- Xint read_varlabel(strp, labeltab, valp)
- Xchar **strp;
- Xlabelv *labeltab;
- Xint *valp;
- X{
- X char *str;
- X labelv *lp;
- X
- X for (str = *strp ; *str && index(VARSEP, *str) != 0 ; str++ );
- X
- X for (lp = labeltab ; lp->label != NULL ; lp++) {
- X if (substrp(str, lp->label)) {
- X *valp = lp->value;
- X str = index(str, '=');
- X if (str == NULL)
- X return(FALSE);
- X str++;
- X *strp = str;
- X return(TRUE);
- X }
- X }
- X *strp = str;
- X return(FALSE);
- X}
- X
- X
- X/* Read a string value from a shell var string.
- X * Return with *strp pointing after the string,
- X * fill in valp with a pointer to a copy of the value string
- X * on the heap.
- X * Return TRUE if things go ok.
- X */
- Xint read_varval(strp, valp)
- Xchar **strp;
- Xchar **valp;
- X{
- X char buf[100], *bp;
- X char *var;
- X
- X var = *strp;
- X bp = buf;
- X while ((*var != NULL) && (index(VARTERM, *var) == NULL)) {
- X *bp = read_slashed(&var);
- X bp++;
- X }
- X *bp = 0;
- X *valp = savestr(buf);
- X *strp = var;
- X return (TRUE);
- X}
- X
- X
- X/* Read the given (slashified) string and return a character.
- X * Advance *strp over chars read.
- X * Handle \\, \001, \n, \t, \r.
- X * The symbol \E maps to escape (\033).
- X * An unexpected char after the slash is just returned.
- X */
- Xint read_slashed(strp)
- Xchar **strp;
- X{
- X char *str;
- X char c;
- X
- X str = *strp;
- X if (*str != '\\') {
- X *strp = (*strp) + 1;
- X return (*str);
- X }
- X str++;
- X c = *str;
- X switch (c) {
- X default:
- X if (index(DIGITS, c) == NULL)
- X break;
- X c -= '0';
- X if (index(DIGITS, str[1]) == NULL)
- X break;
- X str++;
- X c = (c * 8) + (*str - '0');
- X if (index(DIGITS, str[1]) == NULL)
- X break;
- X str++;
- X c = (c * 8) + (*str - '0');
- X break;
- X
- X case 'n':
- X c = '\n';
- X break;
- X
- X case 't':
- X c = '\t';
- X break;
- X
- X case 'E':
- X c = '\033';
- X break;
- X
- X case 'f':
- X c = '\f';
- X break;
- X
- X case 'r':
- X c = '\r';
- X break;
- X }
- X *strp = str + 1;
- X return (c);
- X}
- X
- X
- X/* Turn off flow control characters.
- X */
- Xnoflow()
- X{
- X struct tchars new_tchars;
- X
- X /* Turn off C-Q, C-S flow control. */
- X if (ioctl(0, TIOCGETC, &saved_tchars) < 0) {
- X perror("noflow iocl get");
- X exit(1);
- X }
- X new_tchars = saved_tchars;
- X new_tchars.t_stopc = -1;
- X new_tchars.t_startc = -1;
- X if (ioctl(0, TIOCSETC, &new_tchars) < 0) {
- X perror("noflow iocl set");
- X exit(1);
- X }
- X}
- X
- X
- X/* Restore the flow control characters.
- X */
- Xrestore_flow()
- X{
- X if (ioctl(0, TIOCSETC, &saved_tchars) < 0) {
- X perror("restore_flow iocl set");
- X exit(1);
- X }
- X}
- X
- X
- X/* Read in the termcap strings.
- X */
- Xget_termstrs()
- X{
- X char *term;
- X int res;
- X
- X fr=free_buf;
- X term = getenv("TERM");
- X if (term == NULL) {
- X disperr("The shell variable TERM is not defined.");
- X exit(1);
- X }
- X res = tgetent(buf,term);
- X switch (res) {
- X case -1:
- X disperr("Can't open termcap file.");
- X exit(1);
- X
- X case 0:
- X disperr("No termcap entry for your terminal.");
- X exit(1);
- X
- X default:
- X break;
- X }
- X
- X term_is = tgetstr("is", &fr);
- X if (term_is == NULL)
- X term_is = "";
- X erase_eol = tgetstr("ce", &fr);
- X erase_eos = tgetstr("cd", &fr);
- X erase_scr = tgetstr("cl", &fr);
- X start_so = tgetstr("so", &fr);
- X end_so = tgetstr("se", &fr);
- X start_alt = tgetstr("as", &fr);
- X end_alt = tgetstr("ae", &fr);
- X if (start_alt == 0 || end_alt == 0) {
- X start_alt = "\033F"; /* VT100 default. */
- X end_alt = "\033G";
- X }
- X cm = tgetstr("cm", &fr); /* for cursor positioning */
- X start_kp = tgetstr("ks", &fr);
- X end_kp = tgetstr("ke", &fr);
- X
- X if ((term_is == NULL) || (erase_eol == NULL) ||
- X (erase_eos == NULL) || (erase_scr == NULL) ||
- X (cm == NULL) ||
- X (end_kp == NULL) || (start_kp == NULL) ||
- X (end_alt == NULL) || (start_alt == NULL) ||
- X (end_so == NULL) || (start_so == NULL) ) {
- X disperr("A required termcap capability is missing.");
- X disperr("\t one of: ce, cd, cl, so, se, cm, ks, ke.");
- X exit(1);
- X }
- X
- X /* Now get entries for keymap, NULL means no such entry.
- X */
- X term_f1 = tgetstr("k1", &fr);
- X term_f2 = tgetstr("k2", &fr);
- X term_f3 = tgetstr("k3", &fr);
- X term_f4 = tgetstr("k4", &fr);
- X term_up = tgetstr("ku", &fr);
- X term_down = tgetstr("kd", &fr);
- X term_left = tgetstr("kl", &fr);
- X term_right = tgetstr("kr", &fr);
- X}
- X
- X
- X/* Restore the terminal to its original mode.
- X */
- Xunset_term()
- X{
- X enter_mode(SMNORMAL);
- X Puts(end_kp); /* Can't tell if this is original. */
- X fflush(stdout);
- X nocrmode();
- X echo();
- X restore_flow();
- X resetty();
- X}
- X
- X
- X/* Return the symbol used to display the given char in the
- X * decryption window.
- X */
- Xint char2sym(pchar)
- Xint pchar;
- X{
- X int gchar;
- X
- X if (printable(pchar)) {gchar = pchar;}
- X else if (pchar == -1) {gchar = SUNKNOWN;}
- X else if (notascii(pchar)) {gchar = SNOTASCII;}
- X else if (pchar == '\n') {gchar = SLINEFEED;}
- X else if (pchar == '\r') {gchar = SCARETURN;}
- X else if (pchar == '\f') {gchar = SFORMFEED;}
- X else if (pchar == '\t') {gchar = STAB;}
- X else {gchar = SCONTCODE;}
- X return (gchar);
- X}
- X
- X
- X/* Displays the given symbol on the terminal. Handles
- X * entering and exiting graphics or standout mode.
- X */
- Xputsym(symbol)
- Xint symbol;
- X{
- X int symcode;
- X symgraph *gp;
- X
- X if (! graphic(symbol)) {
- X enter_mode(SMNORMAL);
- X putchar(symbol & CHARM);
- X return;
- X }
- X symcode = symbol & SYMBOLM;
- X if (symcode >= NSYMC) {
- X disperr("Bad symbol code in putsym.");
- X return;
- X }
- X gp = &graphtab[symcode];
- X enter_mode(gp->s_mode);
- X Puts(gp->s_seq);
- X}
- X
- X
- X/* Enter a particular mode. If necessary send escape sequence
- X * to the terminal. Handle terminating the previous mode.
- X */
- Xenter_mode(mode)
- Xint mode;
- X{
- X if (termmode == mode)
- X return;
- X
- X switch (termmode) {
- X case SMNORMAL:
- X break;
- X
- X case SMGRAPHIC:
- X Puts(end_alt);
- X break;
- X
- X case SMSTANDOUT:
- X Puts(end_so);
- X break;
- X
- X default:
- X Puts(end_so);
- X Puts(end_alt);
- X break;
- X }
- X
- X termmode = mode;
- X
- X switch (termmode) {
- X case SMNORMAL:
- X break;
- X
- X case SMGRAPHIC:
- X Puts(start_alt);
- X break;
- X
- X case SMSTANDOUT:
- X Puts(start_so);
- X break;
- X
- X default:
- X disperr("Bad terminal mode.");
- X break;
- X }
- X}
- X
- X
- X/* Return values from srch_ktab().
- X */
- X#define SK_SUBSTR -1
- X#define SK_NOMATCH -2
- X
- X
- X/* Search the key command table for the given keystroke.
- X * If no match, return SK_NOMATCH (which is < 0).
- X * If the keystroke is the prefix for one or more commands,
- X * return SK_SUBSTR (which is < 0).
- X * If an exact match is found, return the index ( >= 0) of
- X * the entry that matched.
- X */
- Xint srch_ktab(ktab, stroke)
- Xkeycmd ktab[];
- Xchar *stroke;
- X{
- X int i;
- X int nsubstr = 0; /* Number of close entries */
- X
- X for (i = 0 ; ktab[i].c_seq != NULL ; i++) {
- X if (strcmp(ktab[i].c_seq, stroke) == 0)
- X return(i);
- X if (substrp(ktab[i].c_seq, stroke))
- X nsubstr++;
- X }
- X if (nsubstr > 0)
- X return (SK_SUBSTR);
- X return (SK_NOMATCH);
- X}
- X
- X
- X/* Return TRUE if the model string starts with the given string.
- X * Return false if strlen(given) > strlen(model).
- X */
- Xint substrp(model, given)
- Xchar *model;
- Xchar *given;
- X{
- X for ( ; (*model != 0) && (*given != 0) ; model++, given++) {
- X if (*model != *given)
- X return (FALSE);
- X }
- X if (*given == 0)
- X return (TRUE);
- X return (FALSE);
- X}
- X
- X
- X/* Read a keystroke from stdin and return the command for it.
- X *
- X * Single character keystrokes not found in the table generate
- X * self-insert commands.
- X * Control characters other than \n, and \t must be quoted in order
- X * to generate self-insert commands. To quote a char, preceed it
- X * by the QUOTEC character.
- X * Multi character keystrokes should end in an exact match. If not,
- X * throw away the char that caused no matches in the keycmdtab,
- X * beep the terminal, and start over.
- X */
- Xint getcmd()
- X{
- X char keystroke[10]; /* Chars in keystroke. */
- X int nchars; /* Length of keystroke[]. */
- X int c;
- X int index; /* Cmd index in keycmdtab. */
- X int code; /* Cmd code. */
- X
- X start_over:
- X nchars = 0;
- X keystroke[0] = 0;
- X
- X while (TRUE) {
- X c = getchar();
- X keystroke[nchars++] = c;
- X keystroke[nchars] = 0;
- X index = srch_ktab(keycmdtab, keystroke);
- X switch (index) {
- X case SK_SUBSTR:
- X continue;
- X
- X case SK_NOMATCH:
- X if (nchars != 1) {
- X beep();
- X goto start_over;
- X }
- X code = CINSERT;
- X if (c == QUOTEC) {
- X c = getchar();
- X break;
- X }
- X else if (printable(c)) {
- X break;
- X }
- X else if ((c != LINEFEED) && (c != TAB)) {
- X beep();
- X goto start_over;
- X }
- X break;
- X
- X default:
- X if (index < 0) {
- X disperr("Bad keycmdtab index.");
- X }
- X code = keycmdtab[index].c_code;
- X break;
- X }
- X return ((code << CMDSHIFT) | (c & CHARM));
- X }
- X}
- X
- X
- X/* Cause the terminal to beep.
- X */
- Xbeep()
- X{
- X Puts("\007"); /* C-G */
- X}
- X
- X
- X/* Save a copy of the given string on the heap.
- X * Return pointer to copy.
- X */
- Xchar *savestr(s)
- Xregister char *s;
- X{
- X char *p;
- X register char *t;
- X
- X if (s == NULL)
- X return( NULL );
- X t = p = (char*) calloc(strlen(s) + 1, 1);
- X if (t == NULL)
- X return(NULL);
- X while (*t++ = *s++);
- X return(p);
- X}
- END_OF_terminal.c
- if test 19285 -ne `wc -c <terminal.c`; then
- echo shar: \"terminal.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 8 \(of 11\).
- cp /dev/null ark8isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 11 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-